package com.adcc.ags.utility.mq.transfer.manager;

import com.adcc.ags.utility.log.Log;
import com.adcc.ags.utility.mq.configuration.MQConfiguration;
import com.adcc.ags.utility.mq.entity.Channel;
import com.adcc.ags.utility.mq.entity.Queue;
import com.adcc.ags.utility.mq.entity.Topic;
import com.adcc.ags.utility.mq.transfer.MQConnectionPool;
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.ibm.mq.MQException;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.CMQC;
import com.ibm.mq.constants.CMQCFC;
import com.ibm.mq.pcf.PCFMessage;
import com.ibm.mq.pcf.PCFMessageAgent;

import java.util.List;

/**
 * Created by zhaoke on 2016/7/6.
 */
public class MQManagerImpl extends MQManager{

    /**
     * 构造函数
     */
    public MQManagerImpl() {
        super();
    }

    /**
     * 构造函数
     * @param configuration
     */
    public MQManagerImpl(MQConfiguration configuration) {
        super(configuration);
    }

    /**
     * 构造函数
     * @param configuration
     * @param connectionPool
     */
    public MQManagerImpl(MQConfiguration configuration,MQConnectionPool connectionPool){
        super(configuration,connectionPool);
    }

    @Override
    public MQQueueManager getQueueManager() throws MQException{
        if(connectionPool == null){
            return new MQQueueManager(configuration.getQueueManager(),configuration.getParams());
        }else{
            return connectionPool.getQueueManager(configuration.getQueueManager(),configuration.getParams());
        }
    }

    @Override
    public void returnQueueManager(MQQueueManager mqm) throws Exception{
        if(mqm != null){
            if(connectionPool == null){
                if(mqm.isConnected()){
                    mqm.disconnect();
                }
                if(mqm.isOpen()){
                    mqm.close();
                }
            }else{
                connectionPool.returnQueueManager(mqm);
            }
        }
    }

    @Override
    public void createChannel(Optional<Channel> channel) throws Exception {
        MQQueueManager mqm = null;
        try{
            if(!channel.isPresent()){
                throw new NullPointerException("channel is null");
            }
            mqm = getQueueManager();
            PCFMessageAgent pcfMessageAgent = new PCFMessageAgent(mqm);
            PCFMessage pcfMessage = new PCFMessage(CMQCFC.MQCMD_CREATE_CHANNEL);
            pcfMessage.addParameter(CMQCFC.MQCACH_CHANNEL_NAME, channel.get().getName());
            pcfMessage.addParameter(CMQCFC.MQIACH_CHANNEL_TYPE, channel.get().getType());
            pcfMessage.addParameter(CMQCFC.MQCACH_MCA_USER_ID, channel.get().getUser());
            pcfMessageAgent.send(pcfMessage);
        }catch (Exception ex){
            Log.error(MQManager.class.getName(),"createChannel() error",ex);
            throw ex;
        }finally {
            returnQueueManager(mqm);
        }
    }

    @Override
    public void deleteChannel(String channel) throws Exception {
        MQQueueManager mqm = null;
        try{
            if(Strings.isNullOrEmpty(channel)){
                throw new NullPointerException("queue is null or empty");
            }
            mqm = getQueueManager();
            PCFMessageAgent pcfMessageAgent = new PCFMessageAgent(mqm);
            PCFMessage pcfMessage = new PCFMessage(CMQCFC.MQCMD_DELETE_CHANNEL);
            pcfMessage.addParameter(CMQCFC.MQCACH_CHANNEL_NAME,channel);
            pcfMessageAgent.send(pcfMessage);
        }catch (Exception ex){
            Log.error(MQManager.class.getName(),"deleteChannel() error",ex);
            throw ex;
        }finally {
            returnQueueManager(mqm);
        }
    }

    @Override
    public void updateChannel(Optional<Channel> channel) throws Exception {
        MQQueueManager mqm = null;
        try{
            if(!channel.isPresent()){
                throw new NullPointerException("channel is null");
            }
            mqm = getQueueManager();
            PCFMessageAgent pcfMessageAgent = new PCFMessageAgent(mqm);
            PCFMessage pcfMessage = new PCFMessage(CMQCFC.MQCMD_CHANGE_CHANNEL);
            pcfMessage.addParameter(CMQCFC.MQCACH_CHANNEL_NAME, channel.get().getName());
            pcfMessage.addParameter(CMQCFC.MQIACH_CHANNEL_TYPE, channel.get().getType());
            pcfMessage.addParameter(CMQCFC.MQCACH_MCA_USER_ID, channel.get().getUser());
            pcfMessageAgent.send(pcfMessage);
        }catch (Exception ex){
            Log.error(MQManager.class.getName(),"createChannel() error",ex);
            throw ex;
        }finally {
            returnQueueManager(mqm);
        }
    }

    @Override
    public List<Channel> findChannel(String name,int type) throws Exception {
        MQQueueManager mqm = null;
        try{
            List<Channel> result = Lists.newArrayList();
            mqm = getQueueManager();
            PCFMessageAgent pcfMessageAgent = new PCFMessageAgent(mqm);
            PCFMessage pcfMessage = new PCFMessage(CMQCFC.MQCMD_INQUIRE_CHANNEL);
            pcfMessage.addParameter(CMQCFC.MQCACH_CHANNEL_NAME, name);
            pcfMessage.addParameter(CMQCFC.MQIACH_CHANNEL_TYPE, type);
            PCFMessage[] messages = pcfMessageAgent.send(pcfMessage);
            if(messages != null && messages.length > 0){
                for(PCFMessage pcf : messages){
                    if(pcf != null){
                        Channel channel = new Channel();
                        channel.setName(pcf.getParameterValue(CMQCFC.MQCACH_CHANNEL_NAME).toString().trim());
                        channel.setType(type);
                        channel.setUser(pcf.getParameterValue(CMQCFC.MQCACH_MCA_USER_ID).toString().trim());
                        result.add(channel);
                    }
                }
            }
            return result;
        }catch (Exception ex){
            Log.error(MQManager.class.getName(),"findChannelß() error",ex);
            throw ex;
        }finally {
            returnQueueManager(mqm);
        }
    }

    @Override
    public List<Channel> findChannel(String name) throws Exception {
        MQQueueManager mqm = null;
        try{
            List<Channel> result = Lists.newArrayList();
            mqm = getQueueManager();
            PCFMessageAgent pcfMessageAgent = new PCFMessageAgent(mqm);
            PCFMessage pcfMessage = new PCFMessage(CMQCFC.MQCMD_INQUIRE_CHANNEL);
            pcfMessage.addParameter(CMQCFC.MQCACH_CHANNEL_NAME, name);
            PCFMessage[] messages = pcfMessageAgent.send(pcfMessage);
            if(messages != null && messages.length > 0){
                for(PCFMessage pcf : messages){
                    if(pcf != null){
                        Channel channel = new Channel();
                        channel.setName(pcf.getParameterValue(CMQCFC.MQCACH_CHANNEL_NAME).toString().trim());
                        channel.setType(Integer.parseInt(pcf.getParameterValue(CMQCFC.MQIACH_CHANNEL_TYPE).toString()));
                        channel.setUser(pcf.getParameterValue(CMQCFC.MQCACH_MCA_USER_ID).toString().trim());
                        result.add(channel);
                    }
                }
            }
            return result;
        }catch (Exception ex){
            Log.error(MQManager.class.getName(),"findChannelß() error",ex);
            throw ex;
        }finally {
            returnQueueManager(mqm);
        }
    }

    @Override
    public void createQueue(Optional<Queue> queue) throws Exception {
        MQQueueManager mqm = null;
        try{
            if(!queue.isPresent()){
                throw new NullPointerException("queue is null");
            }
            mqm = getQueueManager();
            PCFMessageAgent pcfMessageAgent = new PCFMessageAgent(mqm);
            PCFMessage pcfMessage = new PCFMessage(CMQCFC.MQCMD_CREATE_Q);
            pcfMessage.addParameter(CMQC.MQCA_Q_NAME,queue.get().getName());
            pcfMessage.addParameter(CMQC.MQIA_Q_TYPE,queue.get().getType());
            pcfMessage.addParameter(CMQC.MQIA_DEF_PRIORITY,queue.get().getPriority());
            if(queue.get().isPersistent()){
                pcfMessage.addParameter(CMQC.MQIA_DEF_PERSISTENCE,CMQC.MQPER_PERSISTENT);
            }else{
                pcfMessage.addParameter(CMQC.MQIA_DEF_PERSISTENCE,CMQC.MQPER_NOT_PERSISTENT);
            }
            pcfMessage.addParameter(CMQC.MQIA_MAX_Q_DEPTH,queue.get().getDepth());
            pcfMessage.addParameter(CMQC.MQIA_MAX_MSG_LENGTH,queue.get().getMsgMaxLength());
            pcfMessage.addParameter(CMQC.MQIA_RETENTION_INTERVAL,queue.get().getRetainInterval());
            pcfMessageAgent.send(pcfMessage);
        }catch (Exception ex){
            Log.error(MQManager.class.getName(),"createQueue() error",ex);
            throw ex;
        }finally {
            returnQueueManager(mqm);
        }
    }

    @Override
    public void deleteQueue(String queue) throws Exception{
        MQQueueManager mqm = null;
        try{
            if(Strings.isNullOrEmpty(queue)){
                throw new NullPointerException("queue is null or empty");
            }
            mqm = getQueueManager();
            PCFMessageAgent pcfMessageAgent = new PCFMessageAgent(mqm);
            PCFMessage pcfMessage = new PCFMessage(CMQCFC.MQCMD_DELETE_Q);
            pcfMessage.addParameter(CMQC.MQCA_Q_NAME,queue);
            pcfMessageAgent.send(pcfMessage);
        }catch (Exception ex){
            Log.error(MQManager.class.getName(),"deleteQueue() error",ex);
            throw ex;
        }finally {
            returnQueueManager(mqm);
        }
    }

    @Override
    public void updateQueue(Optional<Queue> queue) throws Exception {
        MQQueueManager mqm = null;
        try{
            if(!queue.isPresent()){
                throw new NullPointerException("queue is null");
            }
            mqm = getQueueManager();
            PCFMessageAgent pcfMessageAgent = new PCFMessageAgent(mqm);
            PCFMessage pcfMessage = new PCFMessage(CMQCFC.MQCMD_CHANGE_Q);
            pcfMessage.addParameter(CMQC.MQCA_Q_NAME,queue.get().getName());
            pcfMessage.addParameter(CMQC.MQIA_Q_TYPE,queue.get().getType());
            pcfMessage.addParameter(CMQC.MQIA_DEF_PRIORITY,queue.get().getPriority());
            if(queue.get().isPersistent()){
                pcfMessage.addParameter(CMQC.MQIA_DEF_PERSISTENCE,CMQC.MQPER_PERSISTENT);
            }else{
                pcfMessage.addParameter(CMQC.MQIA_DEF_PERSISTENCE,CMQC.MQPER_NOT_PERSISTENT);
            }
            pcfMessage.addParameter(CMQC.MQIA_MAX_Q_DEPTH,queue.get().getDepth());
            pcfMessage.addParameter(CMQC.MQIA_MAX_MSG_LENGTH,queue.get().getMsgMaxLength());
            pcfMessage.addParameter(CMQC.MQIA_RETENTION_INTERVAL,queue.get().getRetainInterval());
            pcfMessageAgent.send(pcfMessage);
        }catch (Exception ex){
            Log.error(MQManager.class.getName(),"createQueue() error",ex);
            throw ex;
        }finally {
            returnQueueManager(mqm);
        }
    }

    @Override
    public List<Queue> findQueue(String name,int type) throws Exception {
        MQQueueManager mqm = null;
        try{
            List<Queue> result = Lists.newArrayList();
            mqm = getQueueManager();
            PCFMessageAgent pcfMessageAgent = new PCFMessageAgent(mqm);
            PCFMessage pcfMessage = new PCFMessage(CMQCFC.MQCMD_INQUIRE_Q);
            pcfMessage.addParameter(CMQC.MQCA_Q_NAME,name);
            pcfMessage.addParameter(CMQC.MQIA_Q_TYPE,type);
            PCFMessage[] messages = pcfMessageAgent.send(pcfMessage);
            if(messages != null && messages.length > 0){
                for (PCFMessage pcf : messages){
                    if(pcf != null){
                        Queue queue = new Queue();
                        queue.setName(pcf.getParameterValue(CMQC.MQCA_Q_NAME).toString().trim());
                        queue.setType(type);
                        queue.setPriority(pcf.getIntParameterValue(CMQC.MQIA_DEF_PRIORITY));
                        boolean flag = (pcf.getIntParameterValue(CMQC.MQIA_DEF_PERSISTENCE) == 0) ? true : false;
                        queue.setPersistent(flag);
                        queue.setDepth(pcf.getIntParameterValue(CMQC.MQIA_MAX_Q_DEPTH));
                        queue.setMsgMaxLength(pcf.getIntParameterValue(CMQC.MQIA_MAX_MSG_LENGTH));
                        queue.setRetainInterval(pcf.getIntParameterValue(CMQC.MQIA_RETENTION_INTERVAL));
                        result.add(queue);
                    }
                }
            }
            return result;
        }catch (Exception ex){
            Log.error(MQManager.class.getName(),"findQueue() error",ex);
            throw ex;
        }finally {
            returnQueueManager(mqm);
        }
    }

    @Override
    public void createTopic(Optional<Topic> topic) throws Exception {
        MQQueueManager mqm = null;
        try{
            if(!topic.isPresent()){
                throw new NullPointerException("topic is null");
            }
            mqm = getQueueManager();
            PCFMessageAgent pcfMessageAgent = new PCFMessageAgent(mqm);
            PCFMessage pcfMessage = new PCFMessage(CMQCFC.MQCMD_CREATE_TOPIC);
            pcfMessage.addParameter(CMQC.MQCA_TOPIC_NAME,topic.get().getName());
            pcfMessage.addParameter(CMQC.MQCA_TOPIC_STRING,topic.get().getName());
            if(topic.get().getPriority() >= 0){
                pcfMessage.addParameter(CMQC.MQIA_DEF_PRIORITY,topic.get().getPriority());
            }else{
                pcfMessage.addParameter(CMQC.MQIA_DEF_PRIORITY,CMQC.MQPRI_PRIORITY_AS_PARENT);
            }
//            if(topic.get().getType() == CMQC.MQTOPT_LOCAL){
//                pcfMessage.addParameter(CMQC.MQIA_TOPIC_TYPE,topic.get().getType());
//            }else if(topic.get().getType() == CMQC.MQTOPT_CLUSTER){
//                pcfMessage.addParameter(CMQC.MQIA_TOPIC_TYPE,topic.get().getType());
//                pcfMessage.addParameter(CMQC.MQCA_CLUSTER_NAME,"");
//            }
            if(topic.get().isPersistent()){
                pcfMessage.addParameter(CMQC.MQIA_TOPIC_DEF_PERSISTENCE,CMQC.MQPER_PERSISTENT);
            }else{
                pcfMessage.addParameter(CMQC.MQIA_TOPIC_DEF_PERSISTENCE,CMQC.MQPER_NOT_PERSISTENT);
            }
            pcfMessageAgent.send(pcfMessage);
        }catch (Exception ex){
            Log.error(MQManager.class.getName(),"createTopic() error",ex);
            throw ex;
        }finally {
            returnQueueManager(mqm);
        }
    }

    @Override
    public void deleteTopic(String topic) throws Exception {
        MQQueueManager mqm = null;
        try{
            if(Strings.isNullOrEmpty(topic)){
                throw new NullPointerException("topic is null or empty");
            }
            mqm = getQueueManager();
            PCFMessageAgent pcfMessageAgent = new PCFMessageAgent(mqm);
            PCFMessage pcfMessage = new PCFMessage(CMQCFC.MQCMD_DELETE_TOPIC);
            pcfMessage.addParameter(CMQC.MQCA_TOPIC_NAME,topic);
            pcfMessageAgent.send(pcfMessage);
        }catch (Exception ex){
            Log.error(MQManager.class.getName(),"deleteTopic() error",ex);
            throw ex;
        }finally {
            returnQueueManager(mqm);
        }
    }

    @Override
    public void updateTopic(Optional<Topic> topic) throws Exception {
        MQQueueManager mqm = null;
        try{
            if(!topic.isPresent()){
                throw new NullPointerException("topic is null");
            }
            mqm = getQueueManager();
            PCFMessageAgent pcfMessageAgent = new PCFMessageAgent(mqm);
            PCFMessage pcfMessage = new PCFMessage(CMQCFC.MQCMD_CHANGE_TOPIC);
            pcfMessage.addParameter(CMQC.MQCA_TOPIC_NAME,topic.get().getName());
            if(topic.get().getPriority() >= 0){
                pcfMessage.addParameter(CMQC.MQIA_DEF_PRIORITY,topic.get().getPriority());
            }else{
                pcfMessage.addParameter(CMQC.MQIA_DEF_PRIORITY,CMQC.MQPRI_PRIORITY_AS_PARENT);
            }
            if(topic.get().isPersistent()){
                pcfMessage.addParameter(CMQC.MQIA_TOPIC_DEF_PERSISTENCE,CMQC.MQPER_PERSISTENT);
            }else{
                pcfMessage.addParameter(CMQC.MQIA_TOPIC_DEF_PERSISTENCE,CMQC.MQPER_NOT_PERSISTENT);
            }
            pcfMessageAgent.send(pcfMessage);
        }catch (Exception ex){
            Log.error(MQManager.class.getName(),"updateTopic() error",ex);
            throw ex;
        }finally {
            returnQueueManager(mqm);
        }
    }

    @Override
    public List<Topic> findTopic(String name,int type) throws Exception {
        MQQueueManager mqm = null;
        try{
            List<Topic> result = Lists.newArrayList();
            mqm = getQueueManager();
            PCFMessageAgent pcfMessageAgent = new PCFMessageAgent(mqm);
            PCFMessage pcfMessage = new PCFMessage(CMQCFC.MQCMD_INQUIRE_TOPIC);
            pcfMessage.addParameter(CMQC.MQCA_TOPIC_NAME,name);
            pcfMessage.addParameter(CMQC.MQIA_TOPIC_TYPE,type);
            PCFMessage[] messages = pcfMessageAgent.send(pcfMessage);
            if(messages != null && messages.length > 0){
                for (PCFMessage pcf : messages){
                    if(pcf != null){
                        Topic topic = new Topic();
                        topic.setName(pcf.getParameterValue(CMQC.MQCA_TOPIC_NAME).toString().trim());
                        topic.setType(type);
                        topic.setPriority(pcf.getIntParameterValue(CMQC.MQIA_DEF_PRIORITY));
                        boolean flag = (pcf.getIntParameterValue(CMQC.MQIA_TOPIC_DEF_PERSISTENCE) == 1) ? true : false;
                        topic.setPersistent(flag);
                        result.add(topic);
                    }
                }
            }
            return result;
        }catch (Exception ex){
            Log.error(MQManager.class.getName(),"findTopic() error",ex);
            throw ex;
        }finally {
            returnQueueManager(mqm);
        }
    }
}
